﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DBMigrator.Core.DbObjects.Column;
using DBMigrator.Core.DbObjects.ForeignKey;
using Rhino.Mocks;
using StructureMap;
using Xunit;

namespace DBMigrator.Core.Tests.DbObjects.Column
{
    public class ChangeColumnTests
    {
        [Fact]
        public void SqlGenerationTypeShouldReturnIChangeColumn()
        {
            Assert.Equal(typeof(IChangeColumn), new ChangeColumn("Name").SqlGenerationType);
        }

        [Fact]
        public void ConstructorShouldThrowIfCurrentNameIsNull()
        {
            Assert.Throws<ArgumentNullException>(() => new ChangeColumn(null));
        }

        [Fact]
        public void ConstructorShouldThrowIfCurrentNameIsEmpty()
        {
            Assert.Throws<ArgumentNullException>(() => new ChangeColumn(string.Empty));
        }

        [Fact]
        public void ConstructorShouldSetCurrentName()
        {
            var currentName = StringUtil.Random();
            Assert.Equal(currentName, new ChangeColumn(currentName).CurrentName);
        }

        [Fact]
        public void RenameShouldThrowIfNewNameIsNull()
        {
            Assert.Throws<ArgumentNullException>(() => new ChangeColumn("Name").Rename(null));
        }

        [Fact]
        public void RenameShouldThrowIfNewNameIsEmpty()
        {
            Assert.Throws<ArgumentNullException>(() => new ChangeColumn("Name").Rename(string.Empty));
        }

        [Fact]
        public void RenameShouldSetNewName()
        {
            var newName = "New Name";
            Assert.Equal(newName, new ChangeColumn("Name").Rename(newName).NewName);
        }

        [Fact]
        public void RenameShouldReturnChangeColumn()
        {
            var changeColumn = new ChangeColumn("Name");
            Assert.Equal(changeColumn, changeColumn.Rename("New Name"));
        }

        [Fact]
        public void ChangeTypeShouldSetNewType()
        {
            Assert.Equal(typeof(String), new ChangeColumn("Name").ChangeType<String>().NewType);
        }

        [Fact]
        public void ChangeTypeShouldReturnChangeColumn()
        {
            var changeColumn = new ChangeColumn("Name");
            Assert.Equal(changeColumn, changeColumn.ChangeType<String>());
        }

        [Fact]
        public void ChangeLengthShouldThrowIfLengthIsZero()
        {
            Assert.Throws<ArgumentException>(() => new ChangeColumn("Name").ChangeLength(0));
        }

        [Fact]
        public void ChangeLengthShouldSetNewLength()
        {
            uint newLength = 7;
            Assert.Equal(newLength, new ChangeColumn("Name").ChangeLength(newLength).NewLength);
        }

        [Fact]
        public void ChangeLengthShouldReturnChangeColumn()
        {
            var changeColumn = new ChangeColumn("Name");
            Assert.Equal(changeColumn, changeColumn.ChangeLength(2));
        }

        [Fact]
        public void AddForeignKeyShouldThrowIfPrimaryKeyTableIsNull()
        {
            Assert.Throws<ArgumentNullException>(() => new ChangeColumn("Name").AddForeignKey(null, "PrimaryKeyColumn"));
        }

        [Fact]
        public void AddForeignKeyShouldThrowIfPrimaryKeyTableIsEmpty()
        {
            Assert.Throws<ArgumentNullException>(() => new ChangeColumn("Name").AddForeignKey(string.Empty,
                "PrimaryKeyColumn"));
        }

        [Fact]
        public void AddForeignKeyShouldThrowIfPrimaryKeyColumnIsNull()
        {
            Assert.Throws<ArgumentNullException>(() => new ChangeColumn("Name").AddForeignKey("PrimaryKeyTable", null));
        }

        [Fact]
        public void AddForeignKeyShouldThrowIfPrimaryKeyColumnIsEmpty()
        {
            Assert.Throws<ArgumentNullException>(() => new ChangeColumn("Name").AddForeignKey("PrimaryKeyTable",
                string.Empty));
        }

        [Fact]
        public void AddForeignKeyShouldSetForeignKey()
        {
            var primaryKeyTable = StringUtil.Random();
            var primaryKeyColumn = StringUtil.Random();

            var addForeignKey = MockRepository.GenerateMock<IAddForeignKey>();
            ObjectFactory.Inject(addForeignKey);

            Assert.Equal(addForeignKey, new ChangeColumn("Test").AddForeignKey(primaryKeyTable,primaryKeyColumn)
                .NewForeignKey);
        }

        [Fact]
        public void AddForeignKeyShouldReturnAddColumn()
        {
            var addForeignKey = MockRepository.GenerateMock<IAddForeignKey>();
            ObjectFactory.Inject(addForeignKey);

            var changeColumn = new ChangeColumn("Test");

            Assert.Equal(changeColumn, changeColumn.AddForeignKey("Table", "Column"));
        }
    }
}
